package com.itsu.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import com.itsu.admin.service.DataBackUpService;
import com.itsu.job.components.Const;
import com.itsu.job.config.JobProperties;
import com.itsu.job.rpc.model.JobResp;
import com.itsu.job.rpc.util.RpcCallUtil;
import com.itsu.job.rpc.util.RpcResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Jerry.Su
 * @Date 2022/2/10 15:32
 */
@Service
@Slf4j
public class DataBackUpServiceImpl implements DataBackUpService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private JobProperties jobProperties;

    @Override
    public void dataBackUpExport(HttpServletResponse response, boolean containDownNode) throws IOException {
        String nodeStr = stringRedisTemplate.opsForValue().get(Const.REGISTER_RPC_NODES);
        if (!StringUtils.hasText(nodeStr)) {
            log.info("do not found registered node");
            return;
        }
        List<JobResp> jobs = new ArrayList<>();
        for (String node : StrUtil.split(nodeStr, Const.RPC_NODE_SPLIT)) {
            if (containDownNode) {
                List<JobResp> nodeJobs = getDataFromNode(node);
                if (CollUtil.isNotEmpty(nodeJobs)) {
                    jobs.addAll(nodeJobs);
                } else {
                    log.debug("node {} has no job data", node);
                }
            } else {
                String status = stringRedisTemplate.opsForValue().get(node);
                if (Const.UP_STATUS.equals(status)) {
                    List<JobResp> nodeJobs = getDataFromNode(node);
                    if (CollUtil.isNotEmpty(nodeJobs)) {
                        jobs.addAll(nodeJobs);
                    } else {
                        log.debug("node {} has no job data", node);
                    }
                } else {
                    log.debug("node {} status is DOWN", node);
                }
            }
        }

        String tempPath = System.getProperty("java.io.tmpdir");
        String fileName = "export_" + DateUtil.now().replace("-", "").replace(":", "").replace(" ","") + ".txt";
        File file = FileUtil.file(tempPath + File.separator + fileName);
        FileWriter writer = new FileWriter(file);
        writer.writeLines(jobs);

        response.reset();
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            byte[] buff = new byte[1024];
            OutputStream os = response.getOutputStream();
            int i = 0;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            log.error("download fail", e);
        }
    }


    protected List<JobResp> getDataFromNode(String node) {
        RpcResult result = RpcCallUtil.call(node + "/list", "", jobProperties.getRpc().getAccessToken());
        List<JobResp> list = null;
        if (result.getCode() == 0) {
            list = (List<JobResp>) result.getData();
        } else {
            log.debug("get job data from node {} fail, msg is {}", node, result.getMsg());
        }
        return list;
    }

}
